Computer systems typically have operating systems that support multitasking. A multitasking operating system allows multiple tasks (processes) to execute concurrently. For example, a database server process may execute concurrently with many client processes. A client process may request services by issuing a remote procedure call (RPC) to the database server process. A remote procedure call allows a server process to invoke a server procedure on behalf of the client. In conventional systems, the client process issues a remote procedure call by packaging the procedure name and the input parameters into an interprocess communications message and sending the message to the server process. The server process receives the message, unpackages the procedure name and the input parameters, and invokes the named procedure, passing it the unpackaged input parameters. When the procedure completes its execution, the server process packages any output parameters into a message and sends the message to the client process. The client process receives the message and unpackages the output parameters. The process of packaging parameters is known as marshalling, and the process of unpackaging parameters is known as unmarshalling. Using marshalling and unmarshalling to invoke a remote procedure may be disadvantageous because it may impose significant processing overhead (i.e., packaging and unpackaging parameters and sending the interprocess communications message). More specifically, the packaging/unpackaging of parameters and the sending of the interprocess communications message can require the copying of the parameters four distinct times (e.g., (1) copying from a stack of the client process to a client buffer, (2) copying from the client buffer to a kernel buffer, (3) copying from the kernel buffer to a server buffer, and (4) copying from the server buffer to a stack of the server process). Marshalling and unmarshalling may also be disadvantageous because it may require both the server process and the client process know the marshalling/unmarshalling protocol (i.e., the packing format of the interprocess communications message). By requiring the server and client processes to know the marshalling/unmarshalling protocol, the complexity of their code is increased while their portability is reduced.
The present invention is described below using some object-oriented techniques; thus, an overview of well-known object-oriented programming techniques is provided. A common characteristic of object-oriented programming languages is support for data encapsulation. Data encapsulation refers to the binding of functions and data. In the C++ programming language, data encapsulation is supported through the use of classes. A class is a user-defined type. A class declaration describes the data members and function members of the class. A function member is also referred to as a method of a class. The data members and function members of a class are bound together in that when a function member is invoked it operates on a particular occurrence of data members, known as an instance of the class. An instance of a class is also called an object of the class. Thus, a class provides a definition for a group of objects with similar properties and common behavior.
To allocate storage for an object of a particular type (class), an object is instantiated. Once instantiated, data can be assigned to the data members of the particular object. Also, once instantiated, the function members of the particular object can be invoked to access and manipulate the data members. Thus, the function members implement the behavior of the object, and the object provides a structure for encapsulating data and behavior into a single entity.
FIG. 1 is a block diagram illustrating typical data structures used to represent an object. An object is composed of instance data (data members) and function members, which implement the behavior of the object. The data structures used to represent an object comprise an instance data structure 101, a virtual function table 102, and function members 103, 104, 105. The instance data structure 101 contains a pointer to the virtual function table 102 and contains data members. The virtual function table 102 contains an entry for each virtual function member defined for the object. Each entry contains a reference to the code that implements the corresponding function member. The layout of this sample object conforms to models described in U.S. Pat. No. 5,297,284, entitled "A Method for Implementing Virtual Functions and Virtual Bases in a Compiler for an Object Oriented Programming Language," which is hereby incorporated by reference. One skilled in the art would appreciate that other object models can be defined using other programming languages.
An advantage of using object-oriented techniques is that these techniques facilitate the sharing of objects. For example, a process implementing the function members of an instantiated object can share the instantiated object with another process. In this case, the process that implements the function members of the instantiated object is the server process, and the process that remotely invokes the implemented function members is the client process. To access the instantiated object ("real object"), the client invokes the real object's function members. As mentioned above, conventional systems invoke remote procedures using marshalling/unmarshalling techniques. FIG. 2 illustrates these techniques as they are employed in an object-oriented environment (i.e., as they are employed to invoke a real object's function member). The client process creates a proxy object 210 that represents the real object 220. The proxy object contains methods with the same signature as the real object, but with a different implementation. The proxy object's methods do not perform the substantive processing of the real object's methods. Instead, the proxy object's methods perform only preliminary processing that enables the client process to invoke the real object's methods. For example, in conventional systems, each method of the proxy object marshals its name and its input parameters into an interprocess communications message and sends the message to a stub object 230. The stub object then unpacks the message and invokes the named method, passing any input parameters. When the execution of the named method is complete, the stub object marshals the named method's output parameters and sends them to the proxy object. The proxy object unmarshals the output parameters and returns from the invocation of the proxy object. At this point, the client process continues with its normal processing. As mentioned above, however, marshalling/unmarshalling techniques may be undesirable due to the amount of copying involved and due to the processing responsibilities that are imposed on the client and server processes.